package com.zishuimuyu.job.upload;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpConfig;
import cn.hutool.extra.ftp.FtpMode;
import cn.hutool.extra.ssh.Sftp;
import cn.hutool.setting.Setting;
import cn.hutool.setting.SettingUtil;
import com.zishuimuyu.utills.SaveRecordsUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 定时定时任务任务-只用来上传文件
 *
 * @author：GJH
 * @date
 * @company：北京木联能软件股份有限公司
 */
@Slf4j
public class UploadFileJob {
    private static Setting uploadFileSetting = SettingUtil.getFirstFound("config/uploadFile.setting");
    private static Map<String, String> fileTypes = uploadFileSetting.getMap("fileTypes");
    private static String localPath = "";
    private static String localWeatherPath = "";
    private static String localPowerPath = "";
    private static String remotePath = "";
    private static String remoteWeatherPath = "";
    private static String remotePowerPath = "";
    private static String countFilePath = "";
    private static String filePrefix = "";
    private static String fileExtension = "";
    private static String delete = "";

    //静态代码块会在依赖注入后自动执行,并优先执行 下载
    static {
        localPath = uploadFileSetting.getStr("localPath");
        localWeatherPath = uploadFileSetting.getStr("localWeatherPath");
        localPowerPath = uploadFileSetting.getStr("localPowerPath");
        remotePath = uploadFileSetting.getStr("remotePath");
        remoteWeatherPath = uploadFileSetting.getStr("remoteWeatherPath");
        remotePowerPath = uploadFileSetting.getStr("remotePowerPath");
        countFilePath = uploadFileSetting.getStr("countFilePath");
        filePrefix = uploadFileSetting.getStr("filePrefix");
        fileExtension = uploadFileSetting.getStr("fileExtension");
        delete = uploadFileSetting.getStr("delete");
    }

    /**
     * 将要执行的方法所在的类交个spring容器扫描(@Component),并且在要执行的方法上添加@PostConstruct注解或者静态代码块执行**
     *
     * @Postcontruct’在依赖注入完成后自动调用
     */

    public void upload() {
        if ("false".equals(uploadFileSetting.getStr("uploadJobEnable"))) {
            log.info("定时任务上传任务未启用：{}-> {}");
            return;
        }
        log.info("定时任务上传任务启用：{}-> {}", localPath, remotePath);
        String protocol = uploadFileSetting.getStr("protocol");
        String host = uploadFileSetting.getStr("host");
        String charset = uploadFileSetting.getStr("Charset");
        int defaultPort = "sftp".equalsIgnoreCase(protocol) ? 22 : 21;
        Integer port = uploadFileSetting.getInt("port", defaultPort);
        String userName = uploadFileSetting.getStr("userName");
        String passWord = uploadFileSetting.getStr("passWord");
        Long sessionConnectTimeout = uploadFileSetting.getLong("sessionConnectTimeout", 2000L);
        Long channelConnectedTimeout = uploadFileSetting.getLong("channelConnectedTimeout", 2000L);
        FtpConfig ftpConfig = new FtpConfig(host, port, userName, passWord, CharsetUtil.charset(charset));
        ftpConfig.setConnectionTimeout(sessionConnectTimeout);
        ftpConfig.setSoTimeout(channelConnectedTimeout);
        FileUtil.mkdir(localPath);
        FileUtil.mkdir(localWeatherPath);
        FileUtil.mkdir(localPowerPath);
        FileUtil.mkdir(countFilePath);
        List<File> weatherFiles = FileUtil.loopFiles(localWeatherPath);
        List<File> powerFiles = FileUtil.loopFiles(localPowerPath);
        //List<File> files = new ArrayList<>();
        //files.addAll(weatherFiles);
        //files.addAll(powerFiles);
        if (!"*".equals(filePrefix)) {
            //根据filePrefix 前缀过滤
            weatherFiles = weatherFiles.stream().filter(file -> file.getName().startsWith(filePrefix)).collect(Collectors.toList());
            powerFiles = powerFiles.stream().filter(file -> file.getName().startsWith(filePrefix)).collect(Collectors.toList());
        }
        if (!"*".equals(fileExtension)) {
            //根据fileExtension 后缀过滤
            weatherFiles = weatherFiles.stream().filter(file -> file.getName().endsWith(fileExtension)).collect(Collectors.toList());
            powerFiles = powerFiles.stream().filter(file -> file.getName().endsWith(fileExtension)).collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(powerFiles) || CollUtil.isNotEmpty(weatherFiles)) {
            List<String> uploadedFileNameList = new ArrayList<>();
            boolean isDelete = StrUtil.equalsIgnoreCase("true", delete);
            if ("sftp".equalsIgnoreCase(protocol)) {
                uploadedFileNameList.addAll(sftpUpload(ftpConfig, weatherFiles, remoteWeatherPath, isDelete));
                uploadedFileNameList.addAll(sftpUpload(ftpConfig, powerFiles, remotePowerPath, isDelete));
            }
            if ("ftp".equalsIgnoreCase(protocol)) {
                uploadedFileNameList.addAll(ftpUpload(ftpConfig, weatherFiles, remoteWeatherPath, isDelete));
                uploadedFileNameList.addAll(ftpUpload(ftpConfig, powerFiles, remotePowerPath, isDelete));
            }
            //避免重复上传（远端服务器文件未及时删除，会重复下载），先查看已经下载过的文件
            File iniFile = FileUtil.file(countFilePath, "uploadedFileNames.ini");
            SaveRecordsUtil.saveUploadLog(iniFile, uploadedFileNameList, fileTypes);
        } else {
            ThreadUtil.safeSleep(5000);
            return;
        }


    }

    /**
     * sftp上传
     *
     * @param config     配置类
     * @param files      需要上传的文件
     * @param remotePath 服务端路径
     * @param isDelete   上传成功后是否删除本地文件
     * @return java.util.List<java.lang.String>
     */
    public static List<String> sftpUpload(FtpConfig config, List<File> files, String remotePath, boolean isDelete) {
        List<String> uploadedFileList = new ArrayList<>();
        if (CollUtil.isNotEmpty(files)) {
            boolean uploadResult = false;
            Sftp sftp = new Sftp(config);
            for (File file : files) {
                //上传
                uploadResult = sftp.upload(remotePath, file);
                if (uploadResult) {
                    //记录下上传成功的文件
                    uploadedFileList.add(file.getName());
                    log.info("定时任务上传SFTP成功：{}-> {}", file.getAbsolutePath(), remotePath + "/" + file.getName());
                    if (isDelete) {
                        FileUtil.del(file);
                    }
                }
            }
            IoUtil.close(sftp);
        }

        return uploadedFileList;
    }


    /**
     * ftp上传
     *
     * @param config     配置类
     * @param files      需要上传的文件
     * @param remotePath 服务端路径
     * @param isDelete   上传成功后是否删除本地文件
     * @return java.util.List<java.lang.String>
     */
    public static List<String> ftpUpload(FtpConfig config, List<File> files, String remotePath, boolean isDelete) {
        List<String> uploadedFileNameList = new ArrayList<>();
        if (CollUtil.isNotEmpty(files)) {
            boolean uploadResult = false;
            Ftp ftp = new Ftp(config, FtpMode.Active);
            for (File file : files) {
                uploadResult = ftp.upload(remotePath, file);
                if (uploadResult) {
                    uploadedFileNameList.add(file.getName());
                    log.info("定时任务上传FTP成功：{}-> {}", file.getAbsolutePath(), remotePath + "/" + file.getName());
                    if (isDelete) {
                        FileUtil.del(file);
                    }
                }
            }
            IoUtil.close(ftp);
        }

        return uploadedFileNameList;
    }

}
